﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Pai.LiveStation
{
    public abstract class PlayerBase<T> where T: MediaBase, new()
    {
        #region Private Members

        protected string playerName = "Unknown Player";

        //Hub
        protected MediaHubBase hub;

        //Items
        protected HashSet<T> media;

        //Playlist
        protected IPlaylist<T> playlist;
        protected T currentMediaItem;
        protected T nextMediaItem;
        protected bool isPlaying = false;

        private System.Timers.Timer dlRetryTimer;
        private const int retryInterval = 1000;
        protected bool retryDownload = true;
        protected bool downloading = false;

        private System.Timers.Timer broadcastUpdateTimer;
        private const int bUpdateInterval = 10000;

        #endregion

        #region Public Methods
        public PlayerBase(MediaHubBase mediahub)
        {
            SetHub(mediahub);

            dlRetryTimer = new System.Timers.Timer(retryInterval);
            dlRetryTimer.Elapsed += new System.Timers.ElapsedEventHandler(RetryDownload);

            broadcastUpdateTimer = new System.Timers.Timer(bUpdateInterval);
            broadcastUpdateTimer.Elapsed +=new System.Timers.ElapsedEventHandler(CheckAndUpdateBroadcastList);
            broadcastUpdateTimer.Start();
        }

        public PlayerBase(MediaHubBase mediahub, IPlaylist<T> userplaylist) : this(mediahub)
        {
            SetPlaylist(userplaylist);
        }

        public PlayerBase(MediaHubBase mediahub, IPlaylist<T> userplaylist, string name) : this(mediahub, userplaylist)
        {
            Name = name;
        }

        public virtual bool SetHub(MediaHubBase mediahub)
        {
            if (isPlaying)
                return false;

            hub = mediahub;

            return true;
        }

        #region Properties
        public string Name { get { return playerName; } set { playerName = value; } }
        public MediaHubBase Hub { get { return hub; } }
        public T CurrentlyPlaying { get { return currentMediaItem; } }
        public T NextMediaItem { get { return nextMediaItem; } }
        #endregion

        public abstract bool SetPlaylist(IPlaylist<T> userplaylist);
        
        public virtual bool Start()
        {
            if (Advance())
                return isPlaying = true;
            else
                return false;
        }
        public virtual bool Advance()
        {
            if (playlist == null)
                return false;

            if (playlist.Advance())
            {
                currentMediaItem = playlist.Current();
                nextMediaItem = playlist.Next();
                return true;
            }
            else
                return false;
        }

        public virtual void Stop()
        {
            currentMediaItem = null;
            nextMediaItem = null;
            isPlaying = false;
        }

        public void ReDownload()
        {
            if (isPlaying)
                Stop();

            DownloadMedia();
        }

        protected void DownloadMedia()
        {
            Console.WriteLine("Downloading media...\n");
            List<MediaBase> items;

            try
            {
                downloading = true;
                if ((items = hub.GetBroadcastList()) != null)
                {
                    items.ForEach(x => media.Add((T)x));
                }
                dlRetryTimer.Enabled = false;
                downloading = false;
            }
            catch (Exception e)
            {
                downloading = false;
                dlRetryTimer.Start(); 
            }
            //Two exceptions here...a net exception and an insufficient space exception
        }

        #endregion

        private void RetryDownload(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (retryDownload & !downloading)
            {
                Console.WriteLine("Retrying.. \n");
                DownloadMedia();
            }
                
        }

        private void CheckAndUpdateBroadcastList(object sender, System.Timers.ElapsedEventArgs e)
        {
            //TODO
        }
    }
}
